package controller

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/jinzhu/gorm"
	"restful-go/config"
	"restful-go/internal/utils"
	"strconv"
)

type CreateGoodsForm struct {
	GoodsNo        int    `form:"goods_no" binding:"required" json:"goods_no"`
	GoodsName      string `form:"goods_name" binding:"required" json:"goods_name"`
	AtID           int    `form:"at_id" binding:"required" json:"at_id"`
	TotalStock     int    `form:"total_stock" binding:"required,gte=0" json:"total_stock"`
	RemainingStock int    `form:"remaining_stock"  json:"remaining_stock"`
	Price          string `form:"price" binding:"required,gte=0" json:"price"`
}

type EditGoodsForm struct {
	GoodsNo        int    `form:"goods_no" binding:"required" json:"goods_no"`
	GoodsName      string `form:"goods_name" binding:"required" json:"goods_name"`
	AtID           int    `form:"at_id" binding:"required" json:"at_id"`
	Price          string `form:"price" binding:"required,gte=0" json:"price"`
	RemainingStock int    `form:"remaining_stock"  json:"remaining_stock"`
}

type Goods struct {
	Id              int               `json:"id"`
	GoodsNo         int               `json:"goods_no"`
	GoodsName       string            `json:"goods_name"`
	AtID            int               `json:"at_id"`
	TotalStock      int               `json:"total_stock"`
	RemainingStock  int               `json:"remaining_stock"`
	Price           string            `json:"price"`
	Attachment      Attachment        `json:"attachment" gorm:"foreignKey:AtID"`
	InventoryChange []InventoryChange `json:"inventory_change" gorm:"foreignKey:GoodsId"`
}

func (CreateGoodsForm) TableName() string {
	return "goods"
}

func CreateGoods(c *gin.Context) {
	var form CreateGoodsForm
	if err := c.ShouldBindWith(&form, binding.Form); err != nil {
		utils.ErrorJSON(c, 422, err.Error())
		return
	}

	// 创建商品
	goods := &CreateGoodsForm{
		GoodsNo:        form.GoodsNo,
		GoodsName:      form.GoodsName,
		AtID:           form.AtID,
		TotalStock:     form.TotalStock,
		Price:          form.Price,
		RemainingStock: form.TotalStock,
	}
	if err := config.Mysql.Create(goods).Error; err != nil {
		utils.ErrorJSON(c, 422, err.Error())
		return
	}
	utils.SuccessJSON(c, goods)
	return
}

func GetGoods(c *gin.Context) {
	var goods []Goods
	var page, pageSize, totalCount int
	searchText := c.DefaultQuery("search_text", "")

	// 获取分页参数，默认为第一页，每页 10 条记录
	page, _ = strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ = strconv.Atoi(c.DefaultQuery("pageSize", "10"))

	query := config.Mysql.Table("goods")

	// 如果收到了搜索文本，添加搜索条件
	if searchText != "" {
		query = query.Where("(goods_name LIKE ? or goods_no like ?)", "%"+searchText+"%", "%"+searchText+"%")
	}

	query.Model(&Goods{}).Count(&totalCount)

	// 计算 Offset，以确定开始的记录位置
	offset := (page - 1) * pageSize

	// 执行数据库查询，限制记录数量和设置 Offset1
	query.Preload("Attachment").Limit(pageSize).Offset(offset).Order("id desc").Find(&goods)
	utils.SuccessJSON(c, gin.H{
		"list":        goods,
		"total_count": totalCount,
	})
	return
}

func GetGoodsInfo(c *gin.Context) {
	// 从 URL 参数中获取用户ID
	goodsID := c.Param("id")
	var goods Goods
	config.Mysql.Preload("Attachment").
		Preload("InventoryChange", func(db *gorm.DB) *gorm.DB {
			return db.Order("id DESC")
		}).First(&goods, goodsID)
	utils.SuccessJSON(c, goods)
	return
}

func EditGoods(c *gin.Context) {
	goodsID := c.Param("id")

	var form EditGoodsForm
	if err := c.ShouldBindWith(&form, binding.Form); err != nil {
		utils.ErrorJSON(c, 422, err.Error())
		return
	}
	var goods Goods

	config.Mysql.First(&goods, goodsID)
	goods.GoodsNo = form.GoodsNo
	goods.GoodsName = form.GoodsName
	goods.AtID = form.AtID
	goods.Price = form.Price

	// 使用 Save 方法保存用户信息
	config.Mysql.Save(&goods)

	utils.SuccessJSON(c, goods)
	return
}

type InventoryChange struct {
	Id          int    `json:"id"`
	GoodsId     int    `json:"goods_id"`
	Type        int    `json:"type"`
	Inventory   int    `json:"inventory"`
	Description string `json:"description"`
	ChangeTime  string `json:"change_time" gorm:"type:timestamp"`
}

func ChangeInventory(c *gin.Context) {

	goodsID, _ := strconv.Atoi(c.Param("id"))

	inventory, _ := strconv.Atoi(c.PostForm("inventory"))

	changeTime := c.PostForm("change_time")

	inventoryType, _ := strconv.Atoi(c.PostForm("type"))

	var goods Goods

	config.Mysql.First(&goods, goodsID)

	displayType := ""

	// 出库验证库存是否充足
	if inventoryType == 2 {
		if goods.RemainingStock < inventory {
			utils.ErrorJSON(c, 422, "库存不足")
			return
		}
		displayType = "出库"
		goods.RemainingStock = goods.RemainingStock - inventory
	} else {
		goods.TotalStock = goods.TotalStock + inventory
		goods.RemainingStock = goods.RemainingStock + inventory
		displayType = "入库"
	}
	config.Mysql.Save(&goods)

	// 添加变更记录
	changeInventory := &InventoryChange{
		GoodsId:     goodsID,
		Type:        inventoryType,
		ChangeTime:  changeTime,
		Inventory:   inventory,
		Description: fmt.Sprintf("%s %s库存%d件", changeTime, displayType, inventory),
	}

	if err := config.Mysql.Create(changeInventory).Error; err != nil {
		utils.ErrorJSON(c, 422, err.Error())
		return
	}
	utils.SuccessJSON(c, goods)
	return

}
